home *** CD-ROM | disk | FTP | other *** search
/ PC User 2002 August / Disc 1 / PCU0802CD1.iso / software / apps / files / dwmx.exe / Disk1 / data1.cab / Configuration_En / Commands / ServerObject-MasterDetail.js < prev    next >
Encoding:
JavaScript  |  2002-05-22  |  19.6 KB  |  702 lines

  1. // Copyright 2001-2002 Macromedia, Inc. All rights reserved.
  2.  
  3. var HELP_DOC = MM.HELP_objMasterDetail;
  4.  
  5. var _RecordsetName = new RecordsetMenu("","RecordsetName");
  6. var _MasterPageFields = new RecordsetFieldsOrderedList("MasterDetail.htm", "MasterPageFields", "");
  7. var _LinkField = new RecordsetFieldMenu("MasterDetail.htm", "LinkField", "");
  8. var _UniqueKeyField = new RecordsetFieldMenu("MasterDetail.htm", "UniqueKeyField", "");
  9. var _NumRecs = new NumRecButtons("MasterDetail.htm", "NumRecs", "");
  10. var _DetailPageName = new URLTextField("MasterDetail.htm", "DetailPageName", "");
  11. var _DetailPageFields = new RecordsetFieldsOrderedList("MasterDetail.htm", "DetailPageFields", "");
  12. var _Numeric = new CheckBox("MasterDetail.htm","Numeric","");
  13.  
  14. var _documentTypeID = "";
  15.  
  16. //--------------------------------------------------------------------
  17. // FUNCTION:
  18. //   commandButtons
  19. //
  20. // DESCRIPTION:
  21. //   API function for commands. Controls dialog buttons.
  22. //
  23. // ARGUMENTS:
  24. //   none
  25. //
  26. // RETURNS:
  27. //   an array of button names and function calls
  28. //--------------------------------------------------------------------
  29. function commandButtons()
  30. {
  31.   return new Array(MM.BTN_OK,      "clickedOK()",
  32.                    MM.BTN_Cancel,  "window.close()",
  33.                    MM.BTN_Help,    "displayHelp()");
  34. }
  35.  
  36.  
  37.  
  38. //--------------------------------------------------------------------
  39. // FUNCTION:
  40. //   createMasterDetailSet
  41. //
  42. // DESCRIPTION:
  43. //   Inserts the content into the master and detail pages.
  44. //
  45. //   In this implementation, this function is responsible for all
  46. //   insertion work.
  47. //
  48. // ARGUMENTS:
  49. //   paramObj. Contains properties:
  50. //     RecordsetName -- string
  51. //     MasterPageFields -- array
  52. //     DetailPageFields -- array
  53. //     LinkToField -- string
  54. //     UniqueIDField -- string
  55. //     DetailPagePath -- string, relative path from master page
  56. //     DetailPageName -- string, file name only
  57. //     PageSize -- string or number, "all" or positive integer
  58. //
  59. // RETURNS:
  60. //   string - empty upon success, or an error message
  61. //--------------------------------------------------------------------
  62. function createMasterDetailSet(paramObj)
  63. {
  64.   var docURL = dw.getDocumentPath('document');
  65.   var siteURL = dw.getSiteRoot();
  66.   var detailPageName = paramObj.DetailPageName;
  67.   var detailPageAbsURL = dwscripts.getAbsoluteURL(detailPageName,docURL,siteURL);
  68.   var uniqueIDField = paramObj.UniqueIDField;
  69.   _documentTypeID = dw.getDocumentDOM().documentType;
  70.  
  71.   // add recordset parameters. Looks for the recordset paramObj.RecordsetName,
  72.   // and adds its parameters to paramObj
  73.   getRecordsetParameters(paramObj);
  74.   
  75.   paramObj.AddQueryString = "QueryString";
  76.  
  77.   // hava: genericize this so that it is not platform-specific...
  78.   var urlVar = (paramObj.Numeric)?"#URL.recordID#":"'" + "#URL.recordID#" + "'";
  79.   var conditionStr = paramObj.UniqueIDField + " = " + urlVar;
  80.  
  81.   // new SQL statement used in detail page recordset
  82.   paramObj.SQLStatement = editWhereClause(paramObj.SQLStatement,conditionStr);
  83.  
  84.   // add navigation bar parameters
  85.   paramObj.FirstLinkText = MM.LABEL_NewMoveToFirstLinkLabel;
  86.   paramObj.PrevLinkText  = MM.LABEL_NewMoveToPrevLinkLabel;
  87.   paramObj.NextLinkText  = MM.LABEL_NewMoveToNextLinkLabel;
  88.   paramObj.LastLinkText  = MM.LABEL_NewMoveToLastLinkLabel;
  89.  
  90.   // add navigation statistic parameters
  91.   paramObj.beforeFirst = MM.LABEL_RSNavBeforeFirst;
  92.   paramObj.beforeLast  = MM.LABEL_RSNavBeforeLast;
  93.   paramObj.beforeTotal = MM.LABEL_RSNavBeforeTotal;
  94.   paramObj.afterTotal  = MM.LABEL_RSNavAfterTotal;
  95.   paramObj.total = MM.LABEL_RSNavTotal;
  96.   
  97.   if (!dwscripts.selectionIsInBody())
  98.   {
  99.     dwscripts.setCursorToEndOfBody();
  100.   }
  101.  
  102.   // insert content into master page, which is the currently open page
  103.   if (paramObj.PageSize)
  104.     extGroup.queueDocEdits("MasterPageNumRecs",paramObj,null);
  105.   else
  106.     extGroup.queueDocEdits("MasterPageAllRecs",paramObj,null);
  107.   dwscripts.applyDocEdits();
  108.  
  109.  
  110.   // create new or open existing detail page, and prep for insertion
  111.   createAndPrepDetailPage(detailPageName,detailPageAbsURL);
  112.  
  113.   // create unique name for the detail page recordset
  114.   // Note: the below line of code  *must* be placed at a point
  115.   // in the workflow where the Detail Page already has the focus.
  116.   paramObj.RecordsetName = getUniqueRecordsetName();
  117.  
  118.   // insert detail page content into detail page, which is currently open
  119.   extGroup.queueDocEdits("DetailPage",paramObj,null);
  120.   dwscripts.applyDocEdits();
  121.   createLiveDataSettings(); // allow detail page to be viewed with Live Data
  122.  
  123.   // switch focus back to Master Page
  124.   dw.openDocument(docURL);
  125.  
  126.  
  127.   return "";
  128.  
  129. }
  130.  
  131. //--------------------------------------------------------------------
  132. // FUNCTION:
  133. //   createLiveDataSettings
  134. //
  135. // DESCRIPTION:
  136. //   sets the recordID variable to 1 so that page can be previewed
  137. //   from within the application
  138. //
  139. // ARGUMENTS:
  140. //   none
  141. //
  142. // RETURNS:
  143. //   nothing
  144. //--------------------------------------------------------------------
  145. function createLiveDataSettings(detailPageObj)
  146. {
  147.   // NOTE: This is currently Cold Fusion specific
  148.   var str =  "recordID=1";
  149.   dw.setLiveDataParameters(str);
  150. }
  151.  
  152. //--------------------------------------------------------------------
  153. // FUNCTION:
  154. //   clickedOK
  155. //
  156. // DESCRIPTION:
  157. //   verifies data and alerts err msg if invalid.
  158. //   if valid, sets value of MM.cmdReturnValue to parameters and
  159. //   closes dialog
  160. //
  161. // ARGUMENTS:
  162. //   none
  163. //
  164. // RETURNS:
  165. //   an array of button names and function calls
  166. //--------------------------------------------------------------------
  167. function clickedOK()
  168. {
  169.  
  170.   var errMsg = "";
  171.   var detailPageName = _DetailPageName.getValue();
  172.   var masterPageName = dwscripts.getFileName(dw.getDocumentPath("document"));
  173.   var rsName = _RecordsetName.getValue();
  174.   var numRecs = _NumRecs.getValue();
  175.  
  176.   // check that all parameter values are valid
  177.  
  178.   // check detail page name
  179.   if (   !detailPageName || detailPageName.charAt(0) == " "
  180.       || detailPageName.indexOf("/") != -1 
  181.       || (detailPageName.indexOf(".") == 0) 
  182.       || (detailPageName.indexOf(".") == detailPageName.length - 1)
  183.      )
  184.   {
  185.     errMsg = MM.MSG_invalidDetailPageName;
  186.   }
  187.   
  188.   if (!errMsg)
  189.   {
  190.     if (   (detailPageName == masterPageName) 
  191.         || (masterPageName.indexOf(detailPageName + ".") == 0)
  192.        )
  193.     {
  194.       errMsg = MM.MSG_NeedUniqueDetailPageName;
  195.     }
  196.   }
  197.  
  198.   if (!errMsg) // check number of records validity
  199.   {
  200.     errMsg = _NumRecs.applyServerBehavior();
  201.   }
  202.   
  203.   if (!errMsg)
  204.   {
  205.     if (numRecs != "all")
  206.     {
  207.       var sbObj = sbUtils.getRepeatRegionWithPageNav(rsName, true);
  208.       if (sbObj != null)
  209.       {
  210.         errMsg = MM.MSG_RepeatRegionWithPageNavExists;
  211.       }
  212.     }
  213.   }
  214.  
  215.   if (!errMsg) // check that valid columns exist
  216.   {
  217.     var masterFields = _MasterPageFields.getValue();
  218.  
  219.     if((masterFields.length == 0) ||
  220.        (masterFields.length == 1 && masterFields[0].indexOf("MM_ERROR")!=-1))
  221.     {
  222.       errMsg = MM.MSG_columnsEmpty;
  223.     }
  224.   }
  225.  
  226.  
  227.   if (errMsg)
  228.   {
  229.     alert(errMsg);
  230.   }
  231.   else
  232.   {
  233.     paramObj = new Object();
  234.     paramObj.RecordsetName = _RecordsetName.getValue();
  235.     paramObj.MasterPageFields = _MasterPageFields.getValue();
  236.     paramObj.DetailPageFields = _DetailPageFields.getValue();
  237.     paramObj.LinkToField = _LinkField.getValue();
  238.     paramObj.UniqueIDField = _UniqueKeyField.getValue();
  239.     paramObj.DetailPageName = addExtensionToFileName(detailPageName);
  240.     paramObj.PageSize = (_NumRecs.getValue() =="all") ? "":_NumRecs.getValue();
  241.     paramObj.Numeric = _Numeric.getCheckedState();
  242.  
  243.     MM.cmdReturnValue.push(paramObj);
  244.  
  245.     window.close();
  246.   }
  247. }
  248.  
  249.  
  250.  
  251. //--------------------------------------------------------------------
  252. // FUNCTION:
  253. //   initializeUI
  254. //
  255. // DESCRIPTION:
  256. //   Prepare the dialog and controls for user input
  257. //
  258. // ARGUMENTS:
  259. //   none
  260. //
  261. // RETURNS:
  262. //   nothing
  263. //--------------------------------------------------------------------
  264. function initializeUI()
  265. {
  266.   var elts;
  267.  
  268.   _RecordsetName.initializeUI();
  269.   _MasterPageFields.initializeUI();
  270.   _LinkField.initializeUI();
  271.   _UniqueKeyField.initializeUI();
  272.   _NumRecs.initializeUI();
  273.   _DetailPageName.initializeUI();
  274.   _DetailPageFields.initializeUI();
  275.   _Numeric.initializeUI();
  276.  
  277.   elts = document.forms[0].elements;
  278.   if (elts && elts.length)
  279.     elts[0].focus();
  280. }
  281.  
  282.  
  283.  
  284. //-------------------------------------------------------------------
  285. // FUNCTION:
  286. //   displayHelp
  287. //
  288. // DESCRIPTION:
  289. //   displays appropriate help file
  290. //
  291. // ARGUMENTS:
  292. //   none
  293. //
  294. // RETURNS:
  295. //   nothing
  296. //--------------------------------------------------------------------
  297. function displayHelp()
  298. {
  299.   dwscripts.displayDWHelp(HELP_DOC);
  300. }
  301.  
  302.  
  303.  
  304. //--------------------------------------------------------------------
  305. // FUNCTION:
  306. //   updateUI
  307. //
  308. // DESCRIPTION:
  309. //   Called from controls to update the dialog based on user input
  310. //
  311. // ARGUMENTS:
  312. //   whatChanged -- string -- key for which UI element has been updated
  313. //
  314. // RETURNS:
  315. //   nothing
  316. //--------------------------------------------------------------------
  317. function updateUI(whatChanged)
  318. {
  319.   switch (whatChanged)
  320.   {
  321.  
  322.     case "masterFieldsLength":
  323.       var masterFieldsArr = _MasterPageFields.getValue();
  324.       var linkFieldsArr = _LinkField.listControl.list;
  325.  
  326.       if (masterFieldsArr.length != linkFieldsArr.length)
  327.       {
  328.         _LinkField.listControl.setAll(masterFieldsArr,masterFieldsArr);
  329.       }
  330.       break;
  331.  
  332.     default:
  333.       break;
  334.   }
  335. }
  336.  
  337.  
  338. //--------------------------------------------------------------------
  339. // FUNCTION:
  340. //   getUniqueRecordsetName
  341. //
  342. // DESCRIPTION:
  343. //   Returns a unique recordset name for the current document
  344. //
  345. // ARGUMENTS:
  346. //   none
  347. //
  348. // RETURNS:
  349. //   unique recordset name
  350. //--------------------------------------------------------------------
  351. function getUniqueRecordsetName()
  352. {
  353.   var dsNames = dwscripts.getRecordsetNames();
  354.   var nNames = dsNames.length;
  355.   var num = 0;
  356.   var uniqueName = false;
  357.   var rsName = ""
  358.  
  359.   while(!uniqueName)
  360.   {
  361.     num++;
  362.     rsName = "Recordset" + num;
  363.     uniqueName = true;
  364.     for (var i=0;i<nNames;i++)
  365.     {
  366.       if (dsNames.toLowerCase() == rsName.toLowerCase())
  367.       {
  368.         uniqueName = false;
  369.         break;
  370.       }
  371.     }
  372.   }
  373.  
  374.   return rsName;
  375. }
  376.  
  377.  
  378.  
  379. //-------------------------------------------------------------------
  380. // FUNCTION:
  381. //   addExtensionToFileName
  382. //
  383. // DESCRIPTION:
  384. //   Given a file name, check for a file extension, and add a
  385. //   file extension (server-specific) if one does not exist
  386. //
  387. // ARGUMENTS:
  388. //   fileName -- string, file name
  389. //
  390. // RETURNS:
  391. //   file name
  392. //--------------------------------------------------------------------
  393. function addExtensionToFileName(fileName)
  394. {
  395.   var retVal = fileName;
  396.   var hasExtension = (fileName.search(/\.\w+$/) != -1);
  397.  
  398.   if (!hasExtension)
  399.   {
  400.     var fileExtension = dwscripts.getFileExtension(dw.getDocumentDOM().URL)
  401.     retVal = fileName +"." + fileExtension;
  402.   }
  403.  
  404.   return retVal;
  405. }
  406.  
  407. // HE Note: This is modified from the original in Sam's file because I'm passing
  408. // in the entire filter; this makes it generic and easier to copy for multiple users.
  409. // function: editWhereClause -- would better be part of the SQL class
  410.  
  411. // SQL RELATED FUNCTIONS BELOW, should be moved
  412. // They belong in the main SQL function
  413.  
  414. var CONST_where = "WHERE";
  415. var CONST_and = "AND";
  416. var CONST_orderBy = "ORDER BY";
  417. var CONST_groupBy = "GROUP BY";
  418.  
  419. function buildNewSQLSource(sourceStr, index, clause, filter)
  420. {
  421.   var newSource;
  422.  
  423.   newSource = sourceStr.substr(0, index - 1) + " " + clause + " " + filter + " " + sourceStr.substr(index, sourceStr.length - index);
  424.  
  425.   return newSource;
  426.  
  427. }
  428.  
  429. function editWhereClause(SQLStatement,newFilter)
  430. {
  431.  
  432.    //var part = new Participant("recordset_sqlVar");
  433.    var sourceStr = SQLStatement
  434.    var filter = "";
  435.    var newSource = "";
  436.  
  437.    var paramObj = new Object();
  438.    // paramObj.rsName = rsName;
  439.    // paramObj.varName = varName;
  440.  
  441.    // filter = part.getInsertString(paramObj);
  442.  
  443.    // filter = colId + " = " + enclosingToken + filter + enclosingToken;
  444.  
  445.    filter = newFilter;
  446.    var re = new RegExp("\\bwhere\\b","gi");
  447.  
  448.    var index = sourceStr.search(re);
  449.  
  450.    if (index == -1) {
  451.      //The where clause was not found in the sql
  452.  
  453.        var reOrderBy = new RegExp("\\border\\sby\\b","gi");
  454.      var reGroupBy = new RegExp("\\bgroup\\sby\\b","gi");
  455.      var orderIndex = sourceStr.search(reOrderBy);
  456.      var groupIndex = sourceStr.search(reGroupBy);
  457.      if(groupIndex == orderIndex)
  458.      {
  459.          //This can only mean that the group by and order by clause both don't exist (index returns -1).
  460.          newSource = sourceStr + " " + CONST_where + " " + filter;
  461.      } else {
  462.  
  463.          var groupBoolean = new Boolean(false);
  464.  
  465.          // Either group by or order by or both clauses exist in the sql.
  466.        if((groupIndex > -1) && (orderIndex > -1)) {
  467.            // both clause's exist. Check which one has the least index value and insert the filter before it.
  468.          groupBoolean = (groupIndex < orderIndex);
  469.        } else {
  470.            //only one clause exists. Check which one has the greater index value and insert the filter before it.
  471.              groupBoolean = (groupIndex > orderIndex);
  472.        }
  473.        if(groupBoolean)
  474.           newSource = buildNewSQLSource(sourceStr, groupIndex, CONST_where, filter);
  475.        else
  476.           newSource = buildNewSQLSource(sourceStr, orderIndex, CONST_where, filter);
  477.      }
  478.    } else {
  479.        //The sql contains a where clause. We need to find out where it is and insert our filter just after it.
  480.      //The clause generated here will be the only where clause that is used.
  481.      newSource = sourceStr.substr(0, index) + " " + CONST_where + " " + filter;
  482.    }
  483.  
  484.    return newSource;
  485. }
  486.  
  487. //--------------------------------------------------------------------
  488. // FUNCTION:
  489. //   getUniqueRecordsetName
  490. //
  491. // DESCRIPTION:
  492. //   Returns a unique recordset name for the current document
  493. //
  494. // ARGUMENTS:
  495. //   none
  496. //
  497. // RETURNS:
  498. //   unique recordset name
  499. //--------------------------------------------------------------------
  500. function getUniqueRecordsetName()
  501. {
  502.   var dsNames = dwscripts.getRecordsetNames();
  503.   var nNames = dsNames.length;
  504.   var num = 0;
  505.   var uniqueName = false;
  506.   var rsName = ""
  507.  
  508.   while(!uniqueName)
  509.   {
  510.     num++;
  511.     rsName = "Recordset" + num;
  512.     uniqueName = true;
  513.     for (var i=0;i<nNames;i++)
  514.     {
  515.       if (dsNames[i].toLowerCase() == rsName.toLowerCase())
  516.       {
  517.         uniqueName = false;
  518.         break;
  519.       }
  520.     }
  521.   }
  522.  
  523.   return rsName;
  524. }
  525.  
  526. //--------------------------------------------------------------------
  527. // FUNCTION:
  528. //   getSQLStringForURLVariable
  529. //
  530. // DESCRIPTION:
  531. //   Returns url variable surrounded by appropriate delimiters
  532. //
  533. // ARGUMENTS:
  534. //   connName -- string, name of connection. Note: in CF, this is the data source name
  535. //   tableName -- string, name of table
  536. //   colName -- string, name of column
  537. //   varStr -- string, url variable for sql statement, e.g.: #URL.recordID#
  538. //
  539. //
  540. //
  541. // RETURNS:
  542. //   unique recordset name
  543. //--------------------------------------------------------------------
  544. function getSQLStringForURLVariable(connName,tableName,colName,varStr)
  545. {
  546.     var colAndTypes = MMDB.getColumnAndTypeOfTable(connectionName, tableName);
  547.     var nItems = colAndTypes.length;
  548.     var i;
  549.     var colType = "";
  550.     var retVal = colName;
  551.  
  552.     // find colName in colAndTypesArr
  553.     // note that colAndTypes is single dimensional array in form of
  554.     // column name, column type, etc.
  555.  
  556.     for (i=0;i<nItems;i+=2)
  557.     {
  558.       if (colAndTypes[i] == colName)
  559.       {
  560.         colType = colAndTypes[i+1];
  561.       }
  562.     }
  563.  
  564.     // hava: is colType number or string type? Will next clause work?
  565.     if (colType)
  566.     {
  567.       retVal = dwscripts.getSQLStringForDBColumnType(varStr,colType);
  568.     }
  569.     else
  570.     {
  571.       // this case should not be hit, but if it is, use no delimiters
  572.       retVal = varStr;
  573.     }
  574.  
  575.     return retVal;
  576.  
  577.  
  578. }
  579.  
  580. //--------------------------------------------------------------------
  581. // FUNCTION:
  582. //   getRecordsetParameters
  583. //
  584. // DESCRIPTION:
  585. //   Finds paramObj.RecordsetName in the current document, and adds all
  586. //   recordset related parameters to paramObj
  587. //   NOTE: Another way to do this would be use an explicit recordset
  588. //   copying method. hava: is one way preferable over another?
  589. //
  590. // ARGUMENTS:
  591. //   paramObj -- object to store parameters. Must include a property
  592. //   named "RecordsetName" with a valid recordset name.
  593. //   The recordset properties are added to paramObj. Note: this
  594. //   function will override existing paramObj properties of the same
  595. //   name.
  596. //
  597. // RETURNS:
  598. //   nothing. paramObj is passed by reference; return value not needed.
  599. //--------------------------------------------------------------------
  600. function getRecordsetParameters(paramObj)
  601. {
  602.   var sbRecs = dw.sbi.getServerBehaviors();
  603.   var nRecs = sbRecs.length;
  604.   var rsName = paramObj.RecordsetName;
  605.   var i;
  606.   var currRec = "";
  607.  
  608.   for (i=0;i<nRecs;i++)
  609.   {
  610.     currRec = sbRecs[i];
  611.     if (currRec.getName() == "Recordset" && currRec.getParameter("RecordsetName") == rsName)
  612.     {
  613.       rsParamObj = currRec.getParameters();
  614.       break;
  615.     }
  616.   }
  617.  
  618.   // add recordset parameters to paramObj
  619.   for (var i in rsParamObj)
  620.   {
  621.     paramObj[i] = rsParamObj[i];
  622.   }
  623. }
  624.  
  625.  
  626.  
  627.  
  628. // shamelessly copied -- only temporary to focus on major issues first
  629. // add to common dwscripts file? or at least to server behavior file
  630. // in any case, move it!
  631.  
  632. //Invokes dialog to allow user to select filename. Puts value in text input.
  633. // The optional flag stripParameters will remove anything after a question
  634. // mark if it is set to true
  635.  
  636. function browseFile(fieldToStoreURL, stripParameters)
  637. {
  638.   var fileName = "";
  639.   fileName = browseForFileURL();  //returns a local filename
  640.   if (stripParameters) {
  641.     var index = fileName.indexOf("?");
  642.     if (index != -1) {
  643.       fileName = fileName.substring(0,index);
  644.     }
  645.   }
  646.   if (fileName) fieldToStoreURL.value = fileName;
  647. }
  648.  
  649.  
  650. //--------------------------------------------------------------------
  651. // FUNCTION:
  652. //   createAndPrepDetailPage
  653. //
  654. // DESCRIPTION:
  655. //   Looks at detail page name to determine if it exists. Creates
  656. //   file for detail page if it does not already exist. Preps file
  657. //   in either case to ensure that future html insertion will not
  658. //   cause invalid html markup.
  659. //
  660. //
  661. // ARGUMENTS:
  662. //   detailPageName -- string
  663. //   detailPageAbsURL -- string -- detail page absolute path
  664. //   dom (optional) -- document object model for current document
  665. //
  666. //
  667. // RETURNS:
  668. //   nothing
  669. //--------------------------------------------------------------------
  670. function createAndPrepDetailPage(detailPageName,detailPageAbsURL,theDom)
  671. {
  672.   var detailPageExists = dwscripts.fileExists(detailPageAbsURL);
  673.   var detailPageIsOpen = detailPageExists && dwscripts.fileIsCurrentlyOpen(detailPageAbsURL);
  674.   var detailPageIsOpen = false;
  675.   var dom = (theDom)?theDom:dw.getDocumentDOM();
  676.  
  677.   if (detailPageExists)
  678.   {
  679.     dw.openDocument(detailPageAbsURL);
  680.     dom = dw.getDocumentDOM();
  681.  
  682.     if (detailPageIsOpen)
  683.     {
  684.       // move cursor from head, move outside of block tags
  685.       dwscripts.fixUpSelection(dom,false,false);
  686.     }
  687.       else
  688.     {
  689.       // if it was closed, move cursor to the end of the just-opened document
  690.       dwscripts.setCursorToEndOfBody(dom);
  691.     }
  692.   }
  693.  
  694.   else // create a new page to use as the detail page
  695.   {
  696.     dw.createDocument(false, _documentTypeID);
  697.     dom = dw.getDocumentDOM();
  698.     dw.saveDocument(dom,detailPageAbsURL);
  699.   }
  700. }
  701.  
  702.